#include "CMain.h"


CMain::CMain(void)
{
  this->m_pDevice = NULL;
  this->m_pDeviceContext = NULL;
  this->m_pRenderTargetView = NULL;
  this->m_pSwapChain = NULL;
}


CMain::~CMain(void)
{
  if(this->m_pRenderTargetView)
    this->m_pRenderTargetView->Release();
  if(this->m_pSwapChain)
    this->m_pSwapChain->Release();
  if(this->m_pDeviceContext)
    this->m_pDeviceContext->Release();
  if(this->m_pDevice)
    this->m_pDevice->Release();
}

void CMain::Run()
{
  MSG msg;
  msg.message = WM_NULL;
  while(msg.message != WM_QUIT)
  {
    if (PeekMessage(&msg, 0, 0U, 0U, PM_REMOVE))
    {

      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
    else
    {
      float clearColor[4] = {0,0,0,1};
      this->m_pDeviceContext->ClearRenderTargetView(this->m_pRenderTargetView, clearColor);

      this->m_pSwapChain->Present(0,0);
    }
  }
}
//
//int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
//{
//  CMain main;
//  CWindow* window = new CWindow();
//  window->Create(hInstance, "Chess", 100, 100, 300, 300);
//  window->Show();
//  main.SetHWND( window->getHWND());
//
//  main.InitD3D11();
//
//  main.Run();
//}

void CMain::InitD3D11()
{
  DXGI_SWAP_CHAIN_DESC chainDescription;
  ZeroMemory(&chainDescription, sizeof(chainDescription));

  chainDescription.BufferCount = 1;
  chainDescription.BufferDesc.Width = 640;
  chainDescription.BufferDesc.Height = 480;
  chainDescription.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
  chainDescription.BufferDesc.RefreshRate.Numerator = 60;
  chainDescription.BufferDesc.RefreshRate.Denominator = 1;
  chainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  chainDescription.OutputWindow = this->hWindow;
  chainDescription.SampleDesc.Count = 1;
  chainDescription.SampleDesc.Quality = 0;
  chainDescription.Windowed = TRUE;

  D3D_FEATURE_LEVEL featureLevels[] =
  {
    D3D_FEATURE_LEVEL_11_0,
    D3D_FEATURE_LEVEL_10_1,
    D3D_FEATURE_LEVEL_10_0,
  };
  UINT numFeatureLevels = ARRAYSIZE( featureLevels );

  D3D_DRIVER_TYPE driverTypes[] =
  {
    D3D_DRIVER_TYPE_HARDWARE,
    D3D_DRIVER_TYPE_WARP,
    D3D_DRIVER_TYPE_REFERENCE,
  };
  UINT numDriverTypes = ARRAYSIZE( driverTypes );

  HRESULT result;

  D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
  D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_NULL;

  for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
  {
    D3D_DRIVER_TYPE g_driverType = driverTypes[driverTypeIndex];
    result = D3D11CreateDeviceAndSwapChain(NULL, g_driverType, NULL, 0, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &chainDescription, &this->m_pSwapChain, &this->m_pDevice, &featureLevel, &this->m_pDeviceContext);
    if(SUCCEEDED(result)) break;
  }

  ID3D11Texture2D* pBackBuffer = NULL;
  result = this->m_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer );

  result = this->m_pDevice->CreateRenderTargetView( pBackBuffer, NULL, &this->m_pRenderTargetView );
  pBackBuffer->Release();

  this->m_pDeviceContext->OMSetRenderTargets( 1, &this->m_pRenderTargetView, NULL );

  // Setup the viewport
  D3D11_VIEWPORT vp;
  vp.Width = (FLOAT)640;
  vp.Height = (FLOAT)480;
  vp.MinDepth = 0.0f;
  vp.MaxDepth = 1.0f;
  vp.TopLeftX = 0;
  vp.TopLeftY = 0;
  this->m_pDeviceContext->RSSetViewports( 1, &vp );
}

void CMain::SetHWND(HWND window)
{
  this->hWindow = window;
}

HRESULT CMain::CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut )
{
  HRESULT hr = S_OK;

  DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
  // Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
  // Setting this flag improves the shader debugging experience, but still allows 
  // the shaders to be optimized and to run exactly the way they will run in 
  // the release configuration of this program.
  dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif

  ID3DBlob* pErrorBlob;
  hr = D3DX11CompileFromFile( (LPCSTR)szFileName, NULL, NULL, szEntryPoint, szShaderModel, 
    dwShaderFlags, 0, NULL, ppBlobOut, &pErrorBlob, NULL );
  if( FAILED(hr) )
  {
    if( pErrorBlob != NULL )
      OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() );
    if( pErrorBlob ) pErrorBlob->Release();
    return hr;
  }
  if( pErrorBlob ) pErrorBlob->Release();

  return S_OK;
}